package main

import (
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

type RuiningDataStruct struct {
	ID        string `json:"id"`        //唯一ID，即称重记录ID，即某次某个车过磅时，可能有废纸、废塑料，这两个的ID应当不一样
	OrderID   string `json:"orderid"`   //订单ID，即某次某个车过磅时，可能有废纸、废塑料，这两个共用的ID
	Weight    int64  `json:"weight"`    //重量，单位克，只能是整数
	Time      int64  `json:"time"`      //称重时间戳，自1970年过去的秒数
	Kind      string `json:"kind"`      //废旧物品类型: 废纸(fzl)/废塑料(fsl)/废玻璃(fbl)/废金属(fjs)/废纺织品(ffz)
	Sub       string `json:"sub"`       //子类型，子类型没有严格约束，建议取实际业务的品类类型
	StationID string `json:"stationid"` //站点ID，过磅站点ID
	Source    string `json:"source"`    //废旧物品来源：1. 其他站点转运 2 本站点回收
	InData    int64  `json:"indata"`    //减碳量
	Xingzheng string `json:"xingzheng"` //行政区域
	Gongneng  string `json:"gongneng"`  //功能区域
	Project   string `json:"project"`   //项目
}

func CheckWriteIP(WhiteIP map[string]int, Info InfoStruct) bool {
	if WhiteIP == nil {

		return true
	}

	//4. 检查当前访问IP是否在白名单上
	f1 := false
	for _, zn := range Info.IP {
		if WhiteIP[zn] > 0 {
			f1 = true
			break
		}
	}
	return f1
}
func (this ImpInterfaceImp) Ruining_dataupload(w http.ResponseWriter, r *http.Request, Info InfoStruct) {
	//1. 检查项目参数是否合法
	if Info.Project != "RuiningRelease" && Info.Project != "RuiningDebug" {
		ErrorJson(w, -1, "参数错误", Info)
		return
	}

	//2. 检查上传数据的IP是否在白名单
	whites, _ := redisDB.HGet(ctx, Info.Project+":all", "upload:whiteip").Result()
	whitedata := map[string]int{}
	json.Unmarshal([]byte(whites), &whitedata)
	if len(whitedata) > 0 && CheckWriteIP(whitedata, Info) == false {
		ErrorJson(w, -2, "参数错误", Info)
		return
	}

	//3. 检查body是否合法
	data := RuiningDataStruct{}
	e := json.Unmarshal([]byte(Info.Body), &data)
	if e != nil {
		ErrorJson(w, -3, "参数错误", Info)
		return
	}

	//4. 检查参数是否合法
	if data.ID == "" || data.OrderID == "" || data.Weight < 0 || data.Time <= 0 || data.StationID == "" || (data.Source != "1" && data.Source != "2") {
		ErrorJson(w, -4, "参数错误", Info)
		return
	}

	//5. 检查品类是否合法
	if data.Kind != "fzl" && data.Kind != "fsl" && data.Kind != "fbl" && data.Kind != "fjs" && data.Kind != "ffz" {
		ErrorJson(w, -5, "品类不正确", Info)
		return
	}

	//6. 检查站点是否存在
	m, e2 := redisDB.HGet(ctx, Info.Project+":site", data.StationID).Result()
	if e2 != nil || m == "" {
		ErrorJson(w, -6, "站点不存在", Info)
		return
	}
	//7. 检查站点信息是否合法
	StationJSON := map[string]interface{}{}
	e3 := json.Unmarshal([]byte(m), &StationJSON)
	if e3 != nil {
		ErrorJson(w, -7, "站点错误", Info)
		return
	}

	//8. 调整一些参数
	data.Xingzheng = Strval(StationJSON["xingzheng"])
	data.Gongneng = Strval(StationJSON["gongneng"])
	data.Project = Info.Project

	data.InData = data.Weight * 2 //假设每克减碳量为2克

	//9. 存入通道
	RuiningCarbonChan <- data

	//10. 返回成功
	SuccessJson(w, "", Info)

}

func RuiningCalcSub(tablename string, data RuiningDataStruct) {
	redisDB.HIncrBy(ctx, tablename, "weight", data.Weight)
	redisDB.HIncrBy(ctx, tablename, "num", 1)
	redisDB.HIncrBy(ctx, tablename, "in", data.InData)
	//redisDB.HSet(ctx, tablename, "lasttime", data.Time)

	redisDB.HIncrBy(ctx, tablename, data.Kind+":weight", data.Weight)
	redisDB.HIncrBy(ctx, tablename, data.Kind+":num", 1)
	redisDB.HIncrBy(ctx, tablename, data.Kind+":in", data.InData)
	//redisDB.HSet(ctx, tablename, data.SourceStr+":lasttime", data.Time)

	quyu := data.Xingzheng + "_" + data.Gongneng
	redisDB.HIncrBy(ctx, tablename, quyu+":weight", data.Weight)
	redisDB.HIncrBy(ctx, tablename, quyu+":num", 1)
	redisDB.HIncrBy(ctx, tablename, quyu+":in", data.InData)
	//redisDB.HSet(ctx, tablename, quyu+":lasttime", data.Time)

}

func RuiningCarbonThread() {
	var CalcAll = false
	for {
		CbInfo := <-RuiningCarbonChan

		TodayStr := time.Now().Format("20060102")

		//只有自己回收的才能够计入减碳量
		CalcAll = false
		if CbInfo.Source == "2" {
			CalcAll = true
		}
		if CalcAll == true {
			//每日/每月/每年统计表 calc:all:日期
			RuiningCalcSub(CbInfo.Project+":calc:all:all", CbInfo)
			RuiningCalcSub(CbInfo.Project+":calc:all:"+TodayStr, CbInfo)
			RuiningCalcSub(CbInfo.Project+":calc:all:"+TodayStr[0:6], CbInfo)
			RuiningCalcSub(CbInfo.Project+":calc:all:"+TodayStr[0:4], CbInfo)
		}

		//单个站点每日/每月/每年统计表 calc:站点ID:日期
		RuiningCalcSub(CbInfo.Project+":calc:"+CbInfo.StationID+":all", CbInfo)
		RuiningCalcSub(CbInfo.Project+":calc:"+CbInfo.StationID+":"+TodayStr, CbInfo)
		RuiningCalcSub(CbInfo.Project+":calc:"+CbInfo.StationID+":"+TodayStr[0:6], CbInfo)
		RuiningCalcSub(CbInfo.Project+":calc:"+CbInfo.StationID+":"+TodayStr[0:4], CbInfo)

		//存储流水
		ss := strconv.FormatInt(time.Now().UnixNano(), 10) + ":" + CbInfo.ID + ":" + CbInfo.OrderID + ":" + strconv.FormatInt(CbInfo.InData, 10) + ":" + strconv.FormatInt(CbInfo.Weight, 10) + ":" + strconv.FormatInt(+CbInfo.Time, 10) + ":" + CbInfo.Kind + ":" + CbInfo.Source + ":" + CbInfo.Sub
		redisDB.RPush(ctx, CbInfo.Project+":list:"+TodayStr+":"+CbInfo.StationID, ss).Result()

	}
}
